<template>
  <div ref="container" class="radar-container">
    <div ref="radarChart" class="radar-chart"></div>
  </div>
</template>

<script setup lang="ts">
import * as d3 from 'd3';
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';

interface RadarData {
  name: string;
  values: Record<string, number>;
}

interface Margin {
  top: number;
  right: number;
  bottom: number;
  left: number;
}

const props = withDefaults(
  defineProps<{
    data: RadarData[];
    dimensions: string[];
    levels?: number;
    maxValue?: number;
    colors?: string[];
    margin?: Margin;
    aspectRatio?: number; // 宽高比 (width/height)
  }>(),
  {
    levels: 5,
    maxValue: 100,
    colors: () => ['#FF4560', '#008FFB', '#00E396', '#FEB019', '#775DD0'],
    margin: () => ({
      top: 20,
      right: 20,
      bottom: 20,
      left: 20
    }),
    aspectRatio: 1 // 默认正方形
  }
);

const container = ref<HTMLElement>();
const radarChart = ref<HTMLElement>();
let resizeObserver: ResizeObserver;
let svg: d3.Selection<SVGGElement, unknown, null, undefined>;

// 响应式绘制图表
const drawChart = () => {
  if (!radarChart.value || !props.data.length) return;

  // 清空容器
  radarChart.value.innerHTML = '';

  // 获取容器实际尺寸
  const containerWidth = container.value?.clientWidth || 0;
  const containerHeight = container.value?.clientHeight || 0;
  
  // 根据宽高比计算实际绘图尺寸
  let width, height;
  if (containerWidth / containerHeight > props.aspectRatio) {
    height = containerHeight;
    width = height * props.aspectRatio;
  } else {
    width = containerWidth;
    height = width / props.aspectRatio;
  }

  // 计算实际绘图区域尺寸
  const innerWidth = width - props.margin.left - props.margin.right;
  const innerHeight = height - props.margin.top - props.margin.bottom;
  const radius = Math.min(innerWidth, innerHeight) / 2;
  const angleSlice = (Math.PI * 2) / props.dimensions.length;

  // 创建SVG元素
  const svgElement = d3.select(radarChart.value)
    .append('svg')
    .attr('width', width)
    .attr('height', height)
    .attr('viewBox', `0 0 ${width} ${height}`)
    .attr('preserveAspectRatio', 'xMidYMid meet');

  // 创建绘图区域组
  svg = svgElement.append('g')
    .attr('transform', `translate(${props.margin.left + innerWidth / 2}, ${props.margin.top + innerHeight / 2})`);

  // 其余代码保持不变...
  const levelScale = d3.scaleLinear()
    .range([0, radius])
    .domain([0, props.maxValue]);

    
  // 绘制背景网格
  drawBackgroundGrid(svg, radius, props.levels, angleSlice);
  
  // 绘制轴线
  drawAxes(svg, radius, props.dimensions, angleSlice);
  
  // 绘制数据
  drawData(svg, props.data, props.dimensions, angleSlice, levelScale, props.colors);

  // 绘制标题
  drawTitle(svg, props.data,props.colors,levelScale, width, height);
};

// 绘制背景网格
const drawBackgroundGrid = (
  svg: d3.Selection<SVGGElement, unknown, null, undefined>,
  radius: number,
  levels: number,
  angleSlice: number
) => {
  for (let level = 0; level < levels; level++) {
    const levelFactor = radius * ((level + 1) / levels);
    const points = props.dimensions.map((_, i) => {
      const angle = angleSlice * i - Math.PI / 2;
      return [levelFactor * Math.cos(angle), levelFactor * Math.sin(angle)] as [number, number];
    });

    svg.append('polygon')
      .attr('points', points.map(p => p.join(',')).join(' '))
      .attr('stroke', '#CDCDCD')
      .attr('stroke-width', '0.5')
      .attr('fill', level % 2 === 0 ? '#F8F8F8' : 'none');
  }
};

// 绘制轴线
const drawAxes = (
  svg: d3.Selection<SVGGElement, unknown, null, undefined>,
  radius: number,
  dimensions: string[],
  angleSlice: number
) => {
  dimensions.forEach((dim, i) => {
    const angle = angleSlice * i - Math.PI / 2;
    
    // 绘制轴线
    svg.append('line')
      .attr('x1', 0)
      .attr('y1', 0)
      .attr('x2', radius * Math.cos(angle))
      .attr('y2', radius * Math.sin(angle))
      .attr('stroke', '#CDCDCD')
      .attr('stroke-width', '1');

    // 添加维度标签
    svg.append('text')
      .attr('x', (radius + 10) * Math.cos(angle))
      .attr('y', (radius + 10) * Math.sin(angle))
      .text(dim)
      .attr('text-anchor', angle >= 0 && angle <= Math.PI ? 'start' : 'end')
      .attr('dy', '0.35em')
      .style('font-size', '12px')
      .style('fill', '#666');
  });
};

// 绘制数据
const drawData = (
  svg: d3.Selection<SVGGElement, unknown, null, undefined>,
  data: RadarData[],
  dimensions: string[],
  angleSlice: number,
  levelScale: d3.ScaleLinear<number, number>,
  colors: string[]
) => {
  data.forEach((item, dataIndex) => {
    const points = dimensions.map((dim, i) => {
      const angle = angleSlice * i - Math.PI / 2;
      const value = item.values[dim] || 0;
      return [levelScale(value) * Math.cos(angle), levelScale(value) * Math.sin(angle)] as [number, number];
    });

    const color = colors[dataIndex % colors.length];
    
    // 绘制数据区域
    svg.append('polygon')
      .attr('points', points.map(p => p.join(',')).join(' '))
      .attr('stroke', color)
      .attr('stroke-width', '2')
      .attr('fill', color)
      .attr('fill-opacity', 0.2)
      .attr('class', 'radar-area')
      .on('mouseover', function() {
        d3.select(this).attr('fill-opacity', 0.5);
      })
      .on('mouseout', function() {
        d3.select(this).attr('fill-opacity', 0.2);
      });

    // 绘制数据点
    points.forEach((point, _i) => {
      svg.append('circle')
        .attr('cx', point[0])
        .attr('cy', point[1])
        .attr('r', 3)
        .attr('fill', color)
        .attr('stroke', '#fff')
        .attr('stroke-width', 1);
    });
  });
};
const drawTitle = (
  svg: d3.Selection<SVGGElement, unknown, null, undefined>,
  data: RadarData[],
  colors: string[],
  _levelScale: d3.ScaleLinear<number, number>,
  width: number,
  height: number
) => {
  // 获取SVG容器
  const svgContainer = svg.node()?.parentNode as SVGSVGElement;
  
  // 创建底部标题组
  const titleGroup = d3.select(svgContainer)
    .append('g')
    .attr('class', 'bottom-titles')
    .attr('transform', `translate(${width / 2}, ${height - props.margin.bottom / 2+5})`);

  // 计算每个标题需要的宽度（考虑文本长度）
  const textWidths = data.map(player => {
    const temp = titleGroup.append('text')
      .text(player.name)
      .style('font-size', '14px')
      .style('visibility', 'hidden');
    const width = (temp.node()?.getBBox().width || 80) + 30; // 30是色块和间距
    temp.remove();
    return width;
  });

  // 计算总宽度和起始位置
  const totalWidth = textWidths.reduce((sum, w) => sum + w, 0);
  const startX = -totalWidth / 2;
  
  // 绘制每个标题
  let currentX = startX;
  data.forEach((player, index) => {
    const color = colors[index % colors.length];
    const itemWidth = textWidths[index];
    
    // 标题组
    const itemGroup = titleGroup.append('g')
      .attr('transform', `translate(${currentX + itemWidth / 2}, 0)`)
      .style('cursor', 'pointer')
      .on('mouseover', () => highlightData(index))
      .on('mouseout', resetHighlight);

    // 色块
    itemGroup.append('rect')
      .attr('x', -itemWidth / 2)
      .attr('y', -5)
      .attr('width', 12)
      .attr('height', 12)
      .attr('rx', 2)
      .attr('ry', 2)
      .attr('fill', color);

    // 文本
    itemGroup.append('text')
      .attr('x', -itemWidth / 2 + 20)
      .attr('y', 0)
      .attr('dy', '0.35em')
      .text(player.name)
      .style('font-size', '14px')
      .style('fill', '#333');

    currentX += itemWidth;
  });
};
// 在组件脚本部分添加这两个函数
const highlightData = (index: number) => {
  if (!radarChart.value) return; // 添加空值检查
  if (!svg) return;
  
  // 高亮对应数据区域
  svg.selectAll('.radar-area')
    .attr('fill-opacity', (_, i) => i === index ? 0.5 : 0.1);
    
  // 高亮对应数据点
  svg.selectAll('.radar-point')
    .attr('opacity', (_, i) => i === index ? 1 : 0.3);
    
  // 高亮对应标题
  d3.select(radarChart.value)
    .selectAll('.bottom-titles text')
    .style('font-weight', (_, i) => i === index ? 'bold' : 'normal')
    .style('font-size', (_, i) => i === index ? '14px' : '14px');
};

const resetHighlight = () => {
  if (!radarChart.value) return; // 添加空值检查
  if (!svg) return;
  
  // 重置所有元素
  svg.selectAll('.radar-area')
    .attr('fill-opacity', 0.2);
    
  svg.selectAll('.radar-point')
    .attr('opacity', 1);
    
  d3.select(radarChart.value)
    .selectAll('.bottom-titles text')
    .style('font-weight', 'normal')
    .style('font-size', '14px');
};
// 初始化ResizeObserver
const initResizeObserver = () => {
  if (!container.value) return;
  
  resizeObserver = new ResizeObserver((entries) => {
    for (const entry of entries) {
      if (entry.contentRect) {
        drawChart();
      }
    }
  });
  
  resizeObserver.observe(container.value);
};

// 初始绘制和响应式更新
onMounted(() => {
  drawChart();
  initResizeObserver();
});

onBeforeUnmount(() => {
  if (resizeObserver) {
    resizeObserver.disconnect();
  }
});

watch(() => [props.data, props.dimensions], drawChart, { deep: true });
</script>

<style scoped>
.radar-container {
  width: 100%;
  height: 100%;
  position: relative;
}

.radar-chart {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.radar-chart svg {
  max-width: 100%;
  max-height: 100%;
}

.radar-chart :deep(.radar-area) {
  transition: fill-opacity 0.2s ease;
}
</style>